﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace AB.Common
{
    ///// <summary>
    ///// 数据缓存
    ///// </summary>
    //public static class DataStaticCache
    //{
    //    /// <summary>
    //    /// 数据缓存字典
    //    /// </summary>
    //    private static Dictionary<string, DataStaticCacheModel> CacheDic = new Dictionary<string, DataStaticCacheModel>();
    //    /// <summary>
    //    /// 设置缓存
    //    /// </summary>
    //    /// <typeparam name="T">缓存数据类型</typeparam>
    //    /// <param name="key">缓存数据KEY</param>
    //    /// <param name="data">缓存数据</param>
    //    /// <param name="expires">过期时间（默认无过期时间）</param>
    //    /// <param name="isReplace">如果存在相同KEY是否替换数据（默认为True）</param>
    //    /// <param name="allowGC">允许自动删除过期失效的数据（默认为True）</param>
    //    /// <returns>设置缓存的结果</returns>
    //    public static bool SetCache<T>(string key, T data, DateTime? expires = null, bool isReplace = true, bool allowGC = true)
    //    {
    //        GarbageCollection.Start();
    //        if (!CacheDic.Keys.Contains(key) || isReplace)
    //        {
    //            DataStaticCacheModel model = new DataStaticCacheModel() { Key = key, CacheTime = DateTime.Now, Data = data, DataType = typeof(T), Expires = expires, IsEffective = true, AllowGC = allowGC };
    //            if (CacheDic.Keys.Contains(key))
    //            {
    //                CacheDic[key] = model;
    //            }
    //            else
    //            {
    //                CacheDic.Add(key, model);
    //            }
    //            return true;
    //        }
    //        return false;
    //    }
    //    /// <summary>
    //    /// 获取缓存数据
    //    /// </summary>
    //    /// <typeparam name="T">缓存数据类型</typeparam>
    //    /// <param name="key">缓存数据KEY</param>
    //    /// <returns>缓存数据，如果类型不符、KEY不存在、数据过期、数据失效，将返回T默认值</returns>
    //    public static T GetCache<T>(string key)
    //    {
    //        if (CacheDic.Keys.Contains(key))
    //        {
    //            DataStaticCacheModel model = CacheDic[key];
    //            if (!model.DataType.Equals(typeof(T)))
    //            {
    //                Console.Write("");
    //            }
    //            if (!model.IsEffective)
    //            {
    //                Console.Write("");
    //            }
    //            if (!(model.Expires == null || model.Expires >= DateTime.Now))
    //            {
    //                Console.Write("");
    //            }
    //            if (!model.DataType.Equals(typeof(T)) || !model.IsEffective || !(model.Expires == null || model.Expires >= DateTime.Now))
    //            {
    //                return default(T);
    //            }
    //            return (T)model.Data;
    //        }
    //        return default(T);
    //    }
    //    /// <summary>
    //    /// 删除缓存数据
    //    /// </summary>
    //    /// <param name="key">缓存数据KEY</param>
    //    /// <returns></returns>
    //    public static bool DelCache(string key)
    //    {
    //        if (CacheDic.Keys.Contains(key))
    //        {
    //            return CacheDic.Remove(key);
    //        }
    //        return false;
    //    }
    //    /// <summary>
    //    /// 使数据失效
    //    /// </summary>
    //    /// <param name="key">缓存数据KEY</param>
    //    /// <returns></returns>
    //    public static bool Noneffective(string key)
    //    {
    //        if (CacheDic.Keys.Contains(key))
    //        {
    //            CacheDic[key].IsEffective = false;
    //            return true;
    //        }
    //        return false;
    //    }
    //    /// <summary>
    //    /// 获取数据的类型
    //    /// </summary>
    //    /// <param name="key">缓存数据KEY</param>
    //    /// <returns>类型</returns>
    //    public static Type GetDataType(string key)
    //    {
    //        if (CacheDic.Keys.Contains(key))
    //        {
    //            return CacheDic[key].DataType;
    //        }
    //        return default(Type);
    //    }
    //    /// <summary>
    //    /// 获取所有数据
    //    /// </summary>
    //    /// <returns></returns>
    //    public static List<DataStaticCacheModel> GetAllData()
    //    {
    //        List<DataStaticCacheModel> list = new List<DataStaticCacheModel>();
    //        foreach (var item in CacheDic.Values)
    //        {
    //            list.Add(item);
    //        }
    //        return list;
    //    }
    //    private static System.Timers.Timer GarbageCollection = CreateTimer();
    //    /// <summary>
    //    /// 缓存数据垃圾回收（删除数据过期、数据失效的缓存对象）
    //    /// </summary>
    //    private static System.Timers.Timer CreateTimer()
    //    {
    //        System.Timers.Timer t = new System.Timers.Timer();
    //        t.Interval = 500;
    //        t.Elapsed += (object sender, System.Timers.ElapsedEventArgs ea) =>
    //        {
    //            IEnumerable<DataStaticCacheModel> collection = CacheDic.Values.Where(e => e.AllowGC && (!e.IsEffective || (e.Expires != null && e.Expires < DateTime.Now))).AsEnumerable();
    //            foreach (var item in collection)
    //            {
    //                CacheDic.Remove(item.Key);
    //            }
    //            if (CacheDic.Values.Count < 1)
    //            {
    //                GarbageCollection.Stop();
    //            }
    //        };
    //        return t;
    //    }
    //}

    /// <summary>
    /// 数据缓存（单例版）
    /// </summary>
    public class DataCache
    {
        /// <summary>
        /// 定时回收
        /// </summary>
        private System.Timers.Timer GarbageCollection = null;
        /// <summary>
        /// 定义一个标识确保线程同步
        /// </summary>
        private static readonly object locker = new object();
        /// <summary>
        /// 单例实例
        /// </summary>
        private static DataCache Singleton = null;
        /// <summary>
        /// 禁用公共构造方法
        /// </summary>
        private DataCache()
        {
            GarbageCollection = new System.Timers.Timer();
            GarbageCollection.Stop();
            GarbageCollection.Interval = 500;
            GarbageCollection.Elapsed += (object sender, System.Timers.ElapsedEventArgs ea) =>
             {
                 IEnumerable<DataStaticCacheModel> collection = CacheDic.Values.Where(e => e.AllowGC && (!e.IsEffective || (e.Expires != null && e.Expires < DateTime.Now))).AsEnumerable();
                 foreach (var item in collection)
                 {
                     CacheDic.Remove(item.Key);
                 }
                 if (CacheDic.Values.Count < 1)
                 {
                     GarbageCollection.Stop();
                 }
             };
            
        }
        /// <summary>
        /// 创建单例实例
        /// </summary>
        /// <returns></returns>
        public static DataCache Single()
        {
            if (Singleton == null)
            {
                lock (locker)
                {
                    if (Singleton == null)
                    {
                        Singleton = new Common.DataCache();
                    }
                }
            }
            return Singleton;
        }
        /// <summary>
        /// 数据缓存字典
        /// </summary>
        private Dictionary<string, DataStaticCacheModel> CacheDic = new Dictionary<string, DataStaticCacheModel>();
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T">缓存数据类型</typeparam>
        /// <param name="key">缓存数据KEY</param>
        /// <param name="data">缓存数据</param>
        /// <param name="expires">过期时间（默认无过期时间）</param>
        /// <param name="isReplace">如果存在相同KEY是否替换数据（默认为True）</param>
        /// <param name="allowGC">允许自动删除过期失效的数据（默认为True）</param>
        /// <returns>设置缓存的结果</returns>
        public bool SetCache<T>(string key, T data, DateTime? expires = null, bool isReplace = true, bool allowGC = true)
        {
            GarbageCollection.Start();
            if (!CacheDic.ContainsKey(key) || isReplace)
            {
                DataStaticCacheModel model = new DataStaticCacheModel() { Key = key, CacheTime = DateTime.Now, Data = data, DataType = typeof(T), Expires = expires, IsEffective = true, AllowGC = allowGC };
                CacheDic.AddCoverage(key, model);
                return true;
            }
            return false;
        }
        /// <summary>
        /// 获取缓存数据
        /// </summary>
        /// <typeparam name="T">缓存数据类型</typeparam>
        /// <param name="key">缓存数据KEY</param>
        /// <returns>缓存数据，如果类型不符、KEY不存在、数据过期、数据失效，将返回T默认值</returns>
        public T GetCache<T>(string key)
        {
            if (CacheDic.ContainsKey(key))
            {
                DataStaticCacheModel model = CacheDic[key];
                if (!model.DataType.Equals(typeof(T)))
                {
                    Console.Write("");
                }
                if (!model.IsEffective)
                {
                    Console.Write("");
                }
                if (!(model.Expires == null || model.Expires >= DateTime.Now))
                {
                    Console.Write("");
                }
                if (!model.DataType.Equals(typeof(T)) || !model.IsEffective || !(model.Expires == null || model.Expires >= DateTime.Now))
                {
                    return default(T);
                }
                return (T)model.Data;
            }
            return default(T);
        }
        /// <summary>
        /// 删除缓存数据
        /// </summary>
        /// <param name="key">缓存数据KEY</param>
        /// <returns></returns>
        public bool DelCache(string key)
        {
            if (CacheDic.ContainsKey(key))
            {
                return CacheDic.Remove(key);
            }
            return false;
        }
        /// <summary>
        /// 使数据失效
        /// </summary>
        /// <param name="key">缓存数据KEY</param>
        /// <returns></returns>
        public bool Noneffective(string key)
        {
            if (CacheDic.ContainsKey(key))
            {
                CacheDic[key].IsEffective = false;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 获取数据的类型
        /// </summary>
        /// <param name="key">缓存数据KEY</param>
        /// <returns>类型</returns>
        public Type GetDataType(string key)
        {
            if (CacheDic.ContainsKey(key))
            {
                return CacheDic[key].DataType;
            }
            return default(Type);
        }
        /// <summary>
        /// 获取所有数据
        /// </summary>
        /// <returns></returns>
        public List<DataStaticCacheModel> GetAllData()
        {
            List<DataStaticCacheModel> list = new List<DataStaticCacheModel>();
            foreach (var item in CacheDic.Values)
            {
                list.Add(item);
            }
            return list;
        }
    }
    /// <summary>
    /// 缓存对象
    /// </summary>
    public class DataStaticCacheModel
    {
        /// <summary>
        /// KEY
        /// </summary>
        public string Key { get; set; }
        /// <summary>
        /// 缓存时间
        /// </summary>
        public DateTime CacheTime { get; set; }
        /// <summary>
        /// 过期时间
        /// </summary>
        public DateTime? Expires { get; set; }
        /// <summary>
        /// 是否有效
        /// </summary>
        public bool IsEffective { get; set; }
        /// <summary>
        /// 数据
        /// </summary>
        public object Data { get; set; }
        /// <summary>
        /// 数据类型
        /// </summary>
        public Type DataType { get; set; }
        /// <summary>
        /// 是否允许自动删除
        /// </summary>
        public bool AllowGC { get; set; }
    }
}
